<!--
 * @Author: Igris
 * @Date: 2024-07-01 14:29:39
 * @LastEditors: chenw chenw@qq.com
 * @LastEditTime: 2024-07-09 14:07:32
 * @Description: 表格滚动加载表格
-->
<template>
  <div class="scroll-table">
    <el-table
      :data="tableData"
      style="width: 100%"
      class="scroll_table"
      highlight-current-row
      height="100%"
      :cellStyle="tableStyle.cellStyle"
      show-overflow-tooltip
      :header-cell-style="tableStyle.headerCellStyle"
      @selection-change="handleSelectionChange">
      <el-table-column type="expand" v-if="showExpand">
        <template #default="props">
          <slot name="expand" :row="props.row"></slot>
        </template>
      </el-table-column>
      <el-table-column
        v-if="showSelection"
        type="selection"
        align="center"
        width="60"></el-table-column>
      <el-table-column
        v-if="showIndex"
        type="index"
        label="序号"
        align="center"
        width="80"></el-table-column>
      <el-table-column
        v-for="item in tableConfigs"
        :prop="item.prop"
        :label="item.label"
        :width="item.width"
        :key="item.prop"
        :max-width="item['max-width']"
        :min-width="item['min-width']">
        <template #default="scope">
          <slot :name="item.prop" :row="scope.row">
            {{ scope.row[item.prop] || '-' }}
          </slot>
        </template>
      </el-table-column>
    </el-table>

    <div class="back_top" v-if="scrollHeight > 500" @click="handleBackTop">
      <el-icon><Top /></el-icon>
    </div>

    <div class="loading" v-if="isLoading">
      <el-icon class="is-loading"><Loading /></el-icon>
      <span style="margin-left: 5px">加载中...</span>
    </div>
  </div>
</template>

<script lang="ts" setup generic="T extends Record<string, unknown>">
  import tableStyle from '@/config/third-plugins/element/elTable'
  import { Top, Loading } from '@element-plus/icons-vue'
  import { useDebounceFn } from '@vueuse/core'
  import type { TScrollTableProp } from './types/table'

  const props = withDefaults(defineProps<TScrollTableProp<T>>(), {
    showExpand: false,
    showIndex: false,
    showSelection: false,
    isLoading: false,
    tableConfigs: () => [],
    tableData: () => []
  })

  const emit = defineEmits(['selectionChange', 'load'])
  function handleSelectionChange(event: any) {
    emit('selectionChange', event)
  }

  // 需要添加动画节点的dom元素缓存
  let table: HTMLElement | null = null
  let scrollHeight = ref(0)

  const scrollFunc = () => {
    if (!table) return
    const scrollDistance =
      table.scrollHeight - table.scrollTop - table.clientHeight
    scrollHeight.value = table.scrollTop
    if (scrollDistance <= 1) {
      console.log('🚀 ~ 加载中 ~ ')
      if (props.tableData.length < 1000) {
        emit('load')
        console.log('end...')
      }
    }
  }

  // 返回头部
  const handleBackTop = () => {
    table &&
      table.scrollTo({
        top: 0,
        behavior: 'smooth'
      })
  }

  onMounted(() => {
    table = document.querySelector(
      '.scroll_table .el-table__body-wrapper .el-scrollbar .el-scrollbar__wrap'
    )
    // 添加监听事件
    table!.addEventListener('scroll', useDebounceFn(scrollFunc))
  })

  onUnmounted(() => {
    removeEventListener('scroll', scrollFunc)
  })
</script>

<style scoped lang="scss">
  .scroll-table {
    height: 100%;
    position: relative;
    overflow: hidden;

    .back_top {
      --el-backtop-bg-color: var(--el-bg-color-overlay);
      --el-backtop-text-color: var(--el-color-primary);
      --el-backtop-hover-bg-color: var(--el-border-color-extra-light);
      position: absolute;
      right: 10px;
      bottom: 10px;
      background-color: var(--el-backtop-bg-color);
      width: 40px;
      height: 40px;
      border-radius: 50%;
      color: var(--el-backtop-text-color);
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 20px;
      box-shadow: var(--el-box-shadow-lighter);
      cursor: pointer;
      z-index: 5;
    }

    .loading {
      position: absolute;
      left: 50%;
      bottom: 10px;
      transform: translateX(-50%);
      z-index: 5;
      display: flex;
      align-items: center;
      color: var(--el-text-color);
    }
  }
</style>
